package com.weir.quarkus.base.aspect;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import jakarta.inject.Inject;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
import jakarta.persistence.EntityManager;
import jakarta.ws.rs.core.Response;

import org.hibernate.query.sql.internal.NativeQueryImpl;
//import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.weir.quarkus.base.system.vo.ResultDataVo;
import com.weir.quarkus.base.system.vo.VuePageListVo;

import io.quarkus.runtime.util.StringUtil;
import io.vertx.core.json.JsonObject;
import lombok.extern.slf4j.Slf4j;

@Interceptor // 标识这个是拦截器
@Dict
@Slf4j
class DictDataInterceptor {

	ObjectMapper mapper = new ObjectMapper();

	// 编写环绕通知逻辑
	@AroundInvoke
	Object markInvocation(InvocationContext context) {
		// context包含调用点信息比如method paramter 之类的
//        System.out.println("---------------------before");
//        System.out.println("---------------------getMethod-----" + context.getMethod());
//        System.out.println("---------------------getParameters----" + Arrays.deepToString(context.getParameters()));
//        System.out.println("---------------------getTarget----" + context.getTarget());
//        System.out.println("---------------------getTimer-----" + context.getTimer());
		try {
//        	System.out.println("---------------------proceed-------" + context.proceed());
			
			List<JsonObject> items = new ArrayList<>();
			// 对象字段和字段值
			Map<String, String> fieldValueMap = new HashMap<>();
			// 有字典的字段
			List<Field> dictFieldList = new ArrayList<>();
			// 字典map
			Map<String, List<String>> dataListMap = new HashMap<>();
			
			Object result = context.proceed();
			if (result instanceof Response) {
				if (((Response) result).getEntity() instanceof ResultDataVo) {
//					Object object = ((Response) result).getEntity();
//					Object object2 = ((ResultDataVo) ((Response) result).getEntity()).result;
					for (Object record : ((VuePageListVo) ((ResultDataVo) ((Response) result)
							.getEntity()).result).list) {
						String json = "{}";
						try {
							// 解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
							json = mapper.writeValueAsString(record);
						} catch (JsonProcessingException e) {
							log.error("json解析失败" + e.getMessage(), e);
						}
//						System.out.println("---------------------json-------" + json);
						JsonObject jsonObject = new JsonObject(json);

						for (Field field : getAllFields(record)) {
							String value = jsonObject.getString(field.getName());
							fieldValueMap.put(field.getName(), value);
							if (StringUtil.isNullOrEmpty(value)) {
								continue;
							}

							// 找到字典注解
							if (field.getAnnotation(DictData.class) != null) {
								String code = field.getAnnotation(DictData.class).code();
								String text = field.getAnnotation(DictData.class).text();
								String table = field.getAnnotation(DictData.class).table();
								// 只有code有值
								if (!StringUtil.isNullOrEmpty(code)
										&& (StringUtil.isNullOrEmpty(table) && StringUtil.isNullOrEmpty(text))) {
									if (!dictFieldList.contains(field)) {
										dictFieldList.add(field);
									}
									if (!dataListMap.keySet().contains(code)) {
										dataListMap.put(code, new ArrayList<>(Arrays.asList(value)));
									}
									// code table text 都有值
								} else if (!StringUtil.isNullOrEmpty(code)
										&& (!StringUtil.isNullOrEmpty(table) && !StringUtil.isNullOrEmpty(text))) {
									if (!dictFieldList.contains(field)) {
										dictFieldList.add(field);
									}
									String dictCode = code;
									if (!StringUtil.isNullOrEmpty(table)) {
										dictCode = String.format("%s,%s,%s", table, text, code);
									}
									if (!dataListMap.keySet().contains(dictCode)) {
										dataListMap.put(dictCode, new ArrayList<>(Arrays.asList(value)));
									}else {
										List<String> list = dataListMap.get(dictCode);
										list.add(value);
										dataListMap.put(dictCode, list);
									}
								}

							}
							
							// date类型默认转换string格式化日期
							if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null
									&& jsonObject.getString(field.getName()) != null) {
								jsonObject.put(field.getName(), dateToString(new Date(jsonObject.getLong(field.getName()))));
							}
							
						}
						items.add(jsonObject);
//						System.out.println("---------------------fieldValueMap-------" + fieldValueMap);
//						System.out.println("---------------------dictFieldList-------" + dictFieldList);
//						System.out.println("---------------------dataListMap-------" + dataListMap);
					}
				}

			}
			if (!items.isEmpty()) {				
				Map<String, List<DictVo>> dictMap = getDict(dataListMap);
				jsonRecord(items, dictMap, dictFieldList);
				
				((VuePageListVo) ((ResultDataVo) ((Response) result).getEntity()).result).list = items;
			}
			
			return result;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("---------------------after");
		return null;
	}
	
	private void jsonRecord(List<JsonObject> items,Map<String, List<DictVo>> dictMap,List<Field> dictFieldList) {
		for (JsonObject record : items) {			
			for (Field field : dictFieldList) {
				String code = field.getAnnotation(DictData.class).code();
				String text = field.getAnnotation(DictData.class).text();
				String table = field.getAnnotation(DictData.class).table();
				
				String fieldDictCode = code;
				if (!StringUtil.isNullOrEmpty(table)) {
					fieldDictCode = String.format("%s,%s,%s", table, text, code);
				}
				
				String value = record.getString(field.getName());
				if (!StringUtil.isNullOrEmpty(value)) {
					List<DictVo> dictVos = dictMap.get(fieldDictCode);
					if (dictVos == null || dictVos.isEmpty()) {
						continue;
					}
					for (DictVo dictVo : dictVos) {
						if (dictVo.getValue().equals(value)) {
							record.put(field.getName() + "_text", dictVo.getText());
						}
					}
				}
			}
		}
	}
	
	@Inject
	EntityManager em;
	
	private Map<String, List<DictVo>> getDict(Map<String, List<String>> dataListMap) {
		Map<String, List<DictVo>> textListMap = new HashMap<>();
		for (Entry<String, List<String>> entry  : dataListMap.entrySet()) {
			String dictCode = entry.getKey();
			List<String> dataList = entry.getValue();
			// 去组装原生SQL  (sys_user,email,user_name)（table,text,code）
			if (dictCode.contains(",")) {
				String[] split = dictCode.split(",");
				String table_name = split[0], text = split[1], code = split[2];
				List<DictVo> resultList = em.createNativeQuery("select "+code+" as value,"+text+" as text from "+table_name+" where "+code+" in (?1)")
						.setParameter(1, dataList)
						.unwrap(NativeQueryImpl.class)
				.setResultTransformer(Transformers.aliasToBean(DictVo.class))
				.getResultList();
				System.out.println("-----------resultList--------------" + resultList);
				if (!textListMap.keySet().contains(dictCode)) {
					textListMap.put(dictCode, resultList);
				}else {
					List<DictVo> list = textListMap.get(dictCode);
					list.addAll(resultList);
					textListMap.put(dictCode, list);
				}
			}else { // 去数据字典查询 sys_dict里面的code 然后关联查找sys_dict_item
				
			}
		}
		return textListMap;
	}
	
	public static String dateToString(Date d) {
		SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return aDate.format(d);
	}

	/**
	 * 获取类的所有属性，包括父类
	 * 
	 * @param object
	 * @return
	 */
	public static Field[] getAllFields(Object object) {
		Class<?> clazz = object.getClass();
		List<Field> fieldList = new ArrayList<>();
		while (clazz != null) {
			fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = clazz.getSuperclass();
		}
		Field[] fields = new Field[fieldList.size()];
		fieldList.toArray(fields);
		return fields;
	}
}
